package com.gljx.shiro;


import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.gljx.constant.Constant;
import com.gljx.web.Entity.Handle;
import com.gljx.web.Entity.User;
import com.gljx.web.service.HandelServcie;
import com.gljx.web.service.SysService;

/**
 * 认证、授权
* @author LiXiang
* @date 2017年10月12日 下午4:22:44 
*
 */
public class CustomRealm extends AuthorizingRealm {
	
	private  Logger logger = Logger.getLogger(getClass());
	
	//公盐
	@Value("${password.publicSale}")  
    private int publicSale;
	
	// 注入service
	@Autowired(required = true)
	private SysService sysService;
	
	@Autowired(required = true)
	private HandelServcie handleService;
	
	
	// 设置realm的名称
	@Override
	public void setName(String name) {
		super.setName("customRealm");
	}

	// realm的认证方法，从数据库查询用户信息
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) 
															throws AuthenticationException {
		//========================验证登录================================
		
		// token是用户输入的用户名和密码
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;  
		
		// 第一步从token中取出账户
		String userCode = (String) token.getPrincipal();

		// 第二步：根据用户输入的账户从数据库查询
		User sysUser = null;
		
		sysUser = sysService.selectByPrimaryKey(userCode);
		
		if (sysUser == null) {
			//抛出用户不存在异常  
            throw new UnknownAccountException();//没找到帐号
		}
		//校验
	    SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(  
	    		sysUser.getUserName(), //用户名  
	    		sysUser.getPassword(), //密码  
	            ByteSource.Util.bytes(sysUser.getCredentialsSalt()+publicSale),//salt=username+id+salt  
	            getName()  //realm name  
	    );
		//保存cookie
	    
		logger.info("认证");
		return authenticationInfo;
	}

	// 用于授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		
		//当前用户所有权限
		List<Handle> handles=new ArrayList<>();  
		// 单独定一个集合对象，这里放入发送给realm处理的权限信息，shiro不能直接读取我们自定义的类。
		List<String> permissions = new ArrayList<String>();
		//当前用户所有角色
        List<String> roles=new ArrayList<>(); 
        //用户
		String username= (String) principals.getPrimaryPrincipal(); 
		User user = sysService.selectByPrimaryKey(username);
		/*Session session = SecurityUtils.getSubject().getSession();
		if(user !=null){
			
			session.setAttribute(Constant.UserId_session,user.getId());
			session.setAttribute(Constant.CompanyId_session,user.getFcompanyid());
			session.setAttribute(Constant.CompanyName_session, user.getCompanyName());
		}*/
		//管理员
		if(user !=null && user.getFisAdmin()==1){
			roles.add(Constant.Admin_role);
		}
		authorizationInfo.addRoles(roles);
		//数据库获取所有权限
		handles = handleService.selectHandleByUserName(username);
		if (handles != null) {
			for (Handle handle : handles) {
				if(handle == null ) continue;
				// 将数据库中的权限标签 符放入集合
				permissions.add(handle.getHandleUrl());
			}
		}
		// 查到权限数据，返回授权信息(要包括 上边的permissions)
		// 将上边查询到授权信息填充到simpleAuthorizationInfo对象中
		//simpleAuthorizationInfo.addStringPermissions(permissions);
		//authorizationInfo.addObjectPermission(permission);
		//存入权限
		authorizationInfo.addStringPermissions(permissions);
		logger.info("授权开始");
		return authorizationInfo;
	}

	// 清除缓存
	public void clearCached() {
		PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
		super.clearCache(principals);
	}
}
